package org.blaznyoght.subtitles.ui;

import java.awt.Canvas;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.io.File;
import java.util.Date;
import java.util.List;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.KeyStroke;

import org.blaznyoght.subtitles.model.Collection;
import org.blaznyoght.subtitles.model.Element;
import org.blaznyoght.subtitles.model.Time;
import org.jdesktop.beansbinding.AutoBinding.UpdateStrategy;
import org.jdesktop.beansbinding.BeanProperty;
import org.jdesktop.swingbinding.JTableBinding;
import org.jdesktop.swingbinding.SwingBindings;
import org.videolan.jvlc.JVLC;
import org.videolan.jvlc.MediaPlayer;

public class SwingApplication {

	private JVLC jvlc;
	private JFrame frame;
	private JTable table;
	private JTableBinding<Element, Collection, JTable> jTableBinding;
	
	private JMenuItem playMnuItm;
	private JMenuItem stopMnuItm;

	private Collection subtitles = new Collection();
	
	private File movie;
	
	private MediaPlayer mplayer;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					SwingApplication window = new SwingApplication();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public SwingApplication() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setBounds(100, 100, 450, 300);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().setLayout(
				new BoxLayout(frame.getContentPane(), BoxLayout.X_AXIS));

		table = new JTable();
		table.setShowHorizontalLines(false);
		table.setFillsViewportHeight(true);
		table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
		table.setDefaultRenderer(Time.class, new TimeRenderer());
		table.setDefaultRenderer(String.class, new TextRenderer());
		
		Canvas canvas = new Canvas();
		frame.getContentPane().add(canvas);
		jvlc = new JVLC();
		jvlc.setVideoOutput(canvas);

		JScrollPane scrollPane = new JScrollPane(table);
		frame.getContentPane().add(scrollPane);

		JMenuBar menuBar = new JMenuBar();
		frame.setJMenuBar(menuBar);

		JMenu mnFile = new JMenu("File");
		mnFile.setMnemonic('f');
		menuBar.add(mnFile);

		JMenuItem mntmNewFile = new JMenuItem("New file");
		mntmNewFile.setAccelerator(KeyStroke.getKeyStroke('N', InputEvent.CTRL_DOWN_MASK));
		mntmNewFile.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				setSubtitles(new Collection());
			}
		});
		mnFile.add(mntmNewFile);

		JSeparator separator_1 = new JSeparator();
		mnFile.add(separator_1);

		JMenuItem mntmOpen = new JMenuItem("Open");
		mntmOpen.setAccelerator(KeyStroke.getKeyStroke('O', InputEvent.CTRL_DOWN_MASK));
		mntmOpen.addActionListener(new OpenActionListener(this));
		mnFile.add(mntmOpen);

		JMenuItem mntmSave = new JMenuItem("Save");
		mntmSave.setAccelerator(KeyStroke.getKeyStroke('S', InputEvent.CTRL_DOWN_MASK));
		mntmSave.addActionListener(new SaveActionListener(this));
		mnFile.add(mntmSave);

		JMenuItem mntmSaveAs = new JMenuItem("Save as");
		mntmSaveAs.addActionListener(new SaveActionListener(this));
		mnFile.add(mntmSaveAs);

		JSeparator separator = new JSeparator();
		mnFile.add(separator);

		JMenuItem mntmQuit = new JMenuItem("Quit");
		mntmQuit.setAccelerator(KeyStroke.getKeyStroke('Q', InputEvent.CTRL_DOWN_MASK));
		mntmQuit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				SwingApplication.this.frame.dispose();
			}
		});
		mnFile.add(mntmQuit);

		JMenu mnEdit = new JMenu("Edit");
		mnEdit.setMnemonic('e');
		menuBar.add(mnEdit);

		JMenuItem mntmSelectAll = new JMenuItem("Select all");
		mntmSelectAll.setAccelerator(KeyStroke.getKeyStroke('A', InputEvent.CTRL_DOWN_MASK));
		mnEdit.add(mntmSelectAll);

		JMenuItem mntmCut = new JMenuItem("Cut");
		mntmCut.setAccelerator(KeyStroke.getKeyStroke('X', InputEvent.CTRL_DOWN_MASK));
		mnEdit.add(mntmCut);

		JMenuItem mntmCopy = new JMenuItem("Copy");
		mntmCopy.setAccelerator(KeyStroke.getKeyStroke('C', InputEvent.CTRL_DOWN_MASK));
		mnEdit.add(mntmCopy);

		JMenuItem mntmPaste = new JMenuItem("Paste");
		mntmPaste.setAccelerator(KeyStroke.getKeyStroke('V', InputEvent.CTRL_DOWN_MASK));
		mnEdit.add(mntmPaste);

		JMenu mnSubtitle = new JMenu("Subtitle");
		mnSubtitle.setMnemonic('s');
		menuBar.add(mnSubtitle);

		JMenuItem mntmSynchronize = new JMenuItem("Synchronize");
		mntmSynchronize.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				SynchronizeDialog dialog = new SynchronizeDialog(SwingApplication.this);
				dialog.setVisible(true);
				int[] rows = table.getSelectedRows();
				Time startTime = (Time) table.getValueAt(rows[0], 1);
				Time endTime = (Time) table.getValueAt(rows[rows.length-1], 2);
				dialog.getStartSpinner().setValue(new Date(startTime.getTime()));
				dialog.getEndSpinner().setValue(new Date(endTime.getTime()));
				dialog.setStartRank((Integer) table.getValueAt(rows[0], 0));
				dialog.setEndRank((Integer) table.getValueAt(rows[rows.length-1], 0));
			}
		});
		mnSubtitle.add(mntmSynchronize);

		JMenu mnMovie = new JMenu("Movie");
		mnMovie.setMnemonic('m');
		menuBar.add(mnMovie);
		
		JMenuItem mntmOpenMovie = new JMenuItem("Open movie");
		mntmOpenMovie.addActionListener(new OpenVideoActionListener(this));
		mnMovie.add(mntmOpenMovie);
		
		JSeparator separator_2 = new JSeparator();
		mnMovie.add(separator_2);
		
		ActionListener actionListener = new PlayerActionListener(this);
		playMnuItm = new JMenuItem("play/pause");
		playMnuItm.setEnabled(false);
		playMnuItm.addActionListener(actionListener);
		mnMovie.add(playMnuItm);
		
		stopMnuItm = new JMenuItem("stop");
		stopMnuItm.setEnabled(false);
		stopMnuItm.addActionListener(actionListener);
		mnMovie.add(stopMnuItm);

		JMenu menu = new JMenu("?");
		menu.setMnemonic('?');
		menuBar.add(menu);

		JMenuItem mntmAbout = new JMenuItem("About");
		menu.add(mntmAbout);
		initDataBindings();
	}

	protected void initDataBindings() {
		BeanProperty<Collection, List<Element>> collectionBeanProperty = BeanProperty.create("elements");
		jTableBinding = SwingBindings.createJTableBinding(UpdateStrategy.READ, subtitles, collectionBeanProperty, table);
		//
		BeanProperty<Element, Long> elementBeanProperty = BeanProperty.create("rank");
		JTableBinding<Element, Collection, JTable>.ColumnBinding 
		rankColumn = jTableBinding.addColumnBinding(elementBeanProperty);
		rankColumn.setColumnName("Rank");
		//
		BeanProperty<Element, Long> elementBeanProperty_1 = BeanProperty.create("startTime");
		JTableBinding<Element, Collection, JTable>.ColumnBinding
		startColumn = jTableBinding.addColumnBinding(elementBeanProperty_1, "startTimeColumn");
		startColumn.setColumnName("Start time");
		//
		BeanProperty<Element, Long> elementBeanProperty_2 = BeanProperty.create("endTime");
		JTableBinding<Element, Collection, JTable>.ColumnBinding
		endColumn = jTableBinding.addColumnBinding(elementBeanProperty_2, "endTimeColumn");
		endColumn.setColumnName("End time");
		//
		BeanProperty<Element, String> elementBeanProperty3 = BeanProperty.create("text");
		JTableBinding<Element, Collection, JTable>.ColumnBinding 
		textColumn = jTableBinding.addColumnBinding(elementBeanProperty3);
		textColumn.setColumnName("Subtitle");
		//
		jTableBinding.bind();
	}

	/**
	 * @return the frame
	 */
	public JFrame getFrame() {
		return frame;
	}

	/**
	 * @param frame the frame to set
	 */
	public void setFrame(JFrame frame) {
		this.frame = frame;
	}

	/**
	 * @return the subtitles
	 */
	public Collection getSubtitles() {
		return subtitles;
	}

	/**
	 * @param subtitles the subtitles to set
	 */
	public void setSubtitles(Collection subtitles) {
		this.subtitles = subtitles;
		initDataBindings();
	}

	/**
	 * @return the movie
	 */
	public File getMovie() {
		return movie;
	}

	/**
	 * @param movie the movie to set
	 */
	public void setMovie(File movie) {
		this.movie = movie;
		playMnuItm.setEnabled(true);
		stopMnuItm.setEnabled(true);
	}

	/**
	 * @return the mplayer
	 */
	public MediaPlayer getMplayer() {
		return mplayer;
	}

	/**
	 * @param mplayer the mplayer to set
	 */
	public void setMplayer(MediaPlayer mplayer) {
		this.mplayer = mplayer;
	}
	
	public void playPause() {
		MediaPlayer mplayer = getMplayer();
		if (mplayer != null) {
			if (mplayer.isPlaying()) {
				mplayer.pause();
			}
			else {
				mplayer.play();
			}
		}
		else {
			setMplayer(jvlc.play(movie.getAbsolutePath()));
		}
	}
	
	public void stop() {
		MediaPlayer mplayer = getMplayer();
		if (mplayer != null) {
			if (mplayer.isPlaying()) {
				mplayer.stop();
				mplayer.release();
				setMplayer(null);
			}
		}
		
	}

	public void synchronize(Integer startRank, Time time, Integer endRank,
			Time time2) {
		getSubtitles().synchronize(startRank, time, endRank, time2);
		initDataBindings();
	}
}
